Skip to content

Commit

Permalink
Merged from couchdb-1.0.1 succesfully.
Browse files Browse the repository at this point in the history
  • Loading branch information
YasuhiroABE committed Jan 29, 2011
1 parent bc6b0fc commit 54568fe
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 10 deletions.
1 change: 1 addition & 0 deletions couch_db.hrl
Expand Up @@ -190,6 +190,7 @@
skip = 0,

group_level = 0,
group_numrows = false,

view_type = nil,
include_docs = false,
Expand Down
84 changes: 74 additions & 10 deletions couch_httpd_view.erl
Expand Up @@ -155,15 +155,22 @@ output_reduce_view(Req, Db, View, Group, QueryArgs, nil) ->
group_level = GroupLevel
} = QueryArgs,
CurrentEtag = view_group_etag(Group, Db),
Pid = case get_group_numrows_type(Req) of
true -> spawn_link(fun() -> group_numrows_server() end);
_ -> false
end,
couch_httpd:etag_respond(Req, CurrentEtag, fun() ->
{ok, GroupRowsFun, RespFun} = make_reduce_fold_funs(Req, GroupLevel,
QueryArgs, CurrentEtag, Group#group.current_seq,
#reduce_fold_helper_funs{}),
#reduce_fold_helper_funs{}, Pid),
FoldAccInit = {Limit, Skip, undefined, []},
{ok, {_, _, Resp, _}} = couch_view:fold_reduce(View,
RespFun, FoldAccInit, [{key_group_fun, GroupRowsFun} |
make_key_options(QueryArgs)]),
finish_reduce_fold(Req, Resp)
case get_group_numrows_type(Req) of
true -> finish_reduce_fold(Req, Resp, [], Pid);
_ -> finish_reduce_fold(Req, Resp)
end
end);

output_reduce_view(Req, Db, View, Group, QueryArgs, Keys) ->
Expand All @@ -173,10 +180,14 @@ output_reduce_view(Req, Db, View, Group, QueryArgs, Keys) ->
group_level = GroupLevel
} = QueryArgs,
CurrentEtag = view_group_etag(Group, Db, Keys),
Pid = case get_group_numrows_type(Req) of
true -> spawn_link(fun() -> group_numrows_server() end);
_ -> false
end,
couch_httpd:etag_respond(Req, CurrentEtag, fun() ->
{ok, GroupRowsFun, RespFun} = make_reduce_fold_funs(Req, GroupLevel,
QueryArgs, CurrentEtag, Group#group.current_seq,
#reduce_fold_helper_funs{}),
#reduce_fold_helper_funs{}, Pid),
{Resp, _RedAcc3} = lists:foldl(
fun(Key, {Resp, RedAcc}) ->
% run the reduce once for each key in keys, with limit etc
Expand All @@ -190,7 +201,10 @@ output_reduce_view(Req, Db, View, Group, QueryArgs, Keys) ->
{Resp2, RedAcc2}
end,
{undefined, []}, Keys), % Start with no comma
finish_reduce_fold(Req, Resp, [{update_seq,Group#group.current_seq}])
case get_group_numrows_type(Req) of
true -> finish_reduce_fold(Req, Resp, [{update_seq,Group#group.current_seq}], Pid);
_ -> finish_reduce_fold(Req, Resp, [{update_seq,Group#group.current_seq}])
end
end).

reverse_key_default(?MIN_STR) -> ?MAX_STR;
Expand All @@ -203,6 +217,9 @@ get_stale_type(Req) ->
get_reduce_type(Req) ->
list_to_existing_atom(couch_httpd:qs_value(Req, "reduce", "true")).

get_group_numrows_type(Req) ->
list_to_existing_atom(couch_httpd:qs_value(Req, "group_numrows", "false")).

load_view(Req, Db, {ViewDesignId, ViewName}, Keys) ->
Stale = get_stale_type(Req),
Reduce = get_reduce_type(Req),
Expand Down Expand Up @@ -303,6 +320,8 @@ parse_view_param("reduce", Value) ->
[{reduce, parse_bool_param(Value)}];
parse_view_param("include_docs", Value) ->
[{include_docs, parse_bool_param(Value)}];
parse_view_param("group_numrows", Value) ->
[{group_numrows, parse_bool_param(Value)}];
parse_view_param("list", Value) ->
[{list, ?l2b(Value)}];
parse_view_param("callback", _) ->
Expand Down Expand Up @@ -387,6 +406,8 @@ validate_view_query(include_docs, true, Args) ->
% Use the view_query_args record's default value
validate_view_query(include_docs, _Value, Args) ->
Args;
validate_view_query(group_numrows, _Value, Args) ->
Args;
validate_view_query(extra, _Value, Args) ->
Args.

Expand All @@ -395,7 +416,7 @@ make_view_fold_fun(Req, QueryArgs, Etag, Db, UpdateSeq, TotalViewCount, HelperFu
start_response = StartRespFun,
send_row = SendRowFun,
reduce_count = ReduceCountFun
} = apply_default_helper_funs(HelperFuns),
} = apply_default_helper_funs(HelperFuns, Req, Req),

#view_query_args{
include_docs = IncludeDocs
Expand Down Expand Up @@ -427,10 +448,13 @@ make_view_fold_fun(Req, QueryArgs, Etag, Db, UpdateSeq, TotalViewCount, HelperFu
end.

make_reduce_fold_funs(Req, GroupLevel, _QueryArgs, Etag, UpdateSeq, HelperFuns) ->
make_reduce_fold_funs(Req, GroupLevel, _QueryArgs, Etag, UpdateSeq, HelperFuns, nil).

make_reduce_fold_funs(Req, GroupLevel, _QueryArgs, Etag, UpdateSeq, HelperFuns, Pid) ->
#reduce_fold_helper_funs{
start_response = StartRespFun,
send_row = SendRowFun
} = apply_default_helper_funs(HelperFuns),
} = apply_default_helper_funs(HelperFuns, Req, Pid),

GroupRowsFun =
fun({_Key1,_}, {_Key2,_}) when GroupLevel == 0 ->
Expand Down Expand Up @@ -490,7 +514,7 @@ apply_default_helper_funs(
#view_fold_helper_funs{
start_response = StartResp,
send_row = SendRow
}=Helpers) ->
}=Helpers, _Req, _Pid) ->
StartResp2 = case StartResp of
undefined -> fun json_view_start_resp/6;
_ -> StartResp
Expand All @@ -506,19 +530,21 @@ apply_default_helper_funs(
send_row = SendRow2
};


apply_default_helper_funs(
#reduce_fold_helper_funs{
start_response = StartResp,
send_row = SendRow
}=Helpers) ->
}=Helpers, Req, Pid) ->
StartResp2 = case StartResp of
undefined -> fun json_reduce_start_resp/4;
_ -> StartResp
end,

SendRow2 = case SendRow of
undefined -> fun send_json_reduce_row/3;
undefined -> case get_group_numrows_type(Req) of
true -> gen_send_json_reduce_row(Pid);
_ -> fun send_json_reduce_row/3
end;
_ -> SendRow
end,

Expand Down Expand Up @@ -588,6 +614,24 @@ send_json_reduce_row(Resp, {Key, Value}, RowFront) ->
send_chunk(Resp, RowFront ++ ?JSON_ENCODE({[{key, Key}, {value, Value}]})),
{ok, ",\r\n"}.

gen_send_json_reduce_row(Pid) ->
fun(_Req, _KV, _RowFront) ->
Pid ! {countup},
{ok, ",\r\n"}
end.

group_numrows_server() ->
group_numrows_server(0).
group_numrows_server(X) ->
receive
{status, From} ->
From ! X, group_numrows_server(X);
{countup} ->
group_numrows_server(X+1);
{stop, From} ->
From ! X, exit(normal)
end.

view_group_etag(Group, Db) ->
view_group_etag(Group, Db, nil).

Expand Down Expand Up @@ -653,6 +697,26 @@ finish_view_fold(Req, TotalRows, Offset, FoldResult, Fields) ->
finish_reduce_fold(Req, Resp) ->
finish_reduce_fold(Req, Resp, []).

get_group_numrows_final_result(Pid) ->
Pid ! {stop, self()},
receive
X -> X
after 80000 ->
0
end.

finish_reduce_fold(Req, Resp, Fields, Pid) ->
case Resp of
undefined ->
send_json(Req, 200, {[
{group_numrows, 0}
] ++ Fields});
Resp ->
X = get_group_numrows_final_result(Pid),
send_chunk(Resp, "{\"group_numrows\":\"" ++ integer_to_list(X) ++ "\"}"),
end_json_response(Resp)
end.

finish_reduce_fold(Req, Resp, Fields) ->
case Resp of
undefined ->
Expand Down

0 comments on commit 54568fe

Please sign in to comment.